package com.fwj.auth.config;

import com.fwj.auth.config.handle.AuthLoginFailureHandle;
import com.fwj.auth.config.handle.AuthLoginSuccessHandler;
import com.fwj.auth.config.handle.AuthLogoutSuccessHandle;
import com.fwj.auth.filter.CommonAuthFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Author: fwj
 * @Data: 2022/2/20 21:12
 * @Version 1.0
 * @Description:
 */

@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthUserService authUserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //替换默认表单校验，使其支持自定义JSON校验
        http.addFilterBefore(commonAuthFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests().anyRequest().authenticated()
                //配置登录选项
                .and().httpBasic()      // 开启httpBasic认证
                .and().formLogin()      //开启表单登录认证
                .loginPage("http://localhost:8080/login")   //配置登录页面
                .loginProcessingUrl("/login")       //配置登录接口
                .usernameParameter("username")       //默认用户名和密码
                .passwordParameter("password")
                .permitAll()        //允许所有人可访问
                .and().logout()     //配置注销选项
                .logoutSuccessUrl("/logout")    //配置注销接口
                .logoutSuccessHandler(new AuthLogoutSuccessHandle())    //配置注销处理器
                .permitAll();
    }

    //配置放开拦截的请求
    @Override
    public void configure(org.springframework.security.config.annotation.web.builders.WebSecurity web) throws Exception {
        web.ignoring().antMatchers()    //配置放开拦截的路径
                .regexMatchers("/login","/user/register","/user/logout",
                        "/user/saveBindAccount","/user/getBindAccount","/user/registerIdentifyingCode"
                );   //正则匹配，满足则放开
    }

    @Override
    public void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
        super.setAuthenticationConfiguration(authenticationConfiguration);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(authUserService)    //配置实际用户校验业务
                .passwordEncoder(passwordEncoder());    //指定加密策略
    }

    /**
     * 注入指定加密工具 BCryptPasswordEncoder()
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置认证管理器，使用自带的AuthenticationManager
     */
    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    /**
     * 注册自定义的commonAuthFilter
     */
    @Bean
    public AbstractAuthenticationProcessingFilter commonAuthFilter() throws Exception {
        AbstractAuthenticationProcessingFilter filter = new CommonAuthFilter();
        filter.setAuthenticationSuccessHandler(new AuthLoginSuccessHandler());
        filter.setAuthenticationFailureHandler(new AuthLoginFailureHandle());
        //过滤器拦截的url要和登录的url一致，否则不生效
        filter.setFilterProcessesUrl("/login");
        //使用自带的AuthenticationManager
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }
}
